/**
 * Peter
 * Created by: Peter Development Team
 *    http://peter.codeplex.com/
 * 
 * GNU General Public License version 2 (GPLv2)
 *    http://peter.codeplex.com/license
 **/

using System;
using System.Collections.ObjectModel;
using System.Linq;
using Peter.Common.MainMenu;
using Peter.Common.Tree;
using Peter.Ftp.DataAccess;

namespace Peter.Ftp.Data
{
   /// <summary>
   /// Represents an ftp item on a ftp server.
   /// </summary>
   public class FtpItem : ModelTreeViewItem
   {
      /// <summary>
      /// Initializes a new Ftp item.
      /// </summary>
      /// <param name="isFolder">True if item is a folder, otherwise false.</param>
      /// <param name="ftpConnection">The main FtpConnection object.</param>
      /// <param name="text">The text for the node.</param>
      /// <param name="parent">Parent, if there is one.</param>
      public FtpItem (bool isFolder, FtpConnection ftpConnection,
         string text, ModelTreeViewItem parent = null)
         : base (parent, isFolder)
      {
         if (ftpConnection == null)
            throw new ArgumentNullException ("ftpConnection");
         if (!ftpConnection.IsConnected)
            throw new InvalidOperationException ("FTP connection is not logged in.");

         this.Connection = ftpConnection;
         this.Text = text;
         this.IsDirectory = isFolder;
         this.IsRoot = parent == null;
         this.SetIcon ();
      }

      /// <summary>
      /// Gets the ftp connection for the item.
      /// </summary>
      public FtpConnection Connection { get; private set; }

      /// <summary>
      /// Gets or Sets if this item is a directory.
      /// </summary>
      public bool IsDirectory { get; private set; }

      /// <summary>
      /// Gets or Sets if this is the root node.
      /// </summary>
      public bool IsRoot { get; private set; }

      /// <summary>
      /// Gets the size of the ftp item.
      /// </summary>
      public long Size { get; set; }

      /// <summary>
      /// Loads any children nodes.
      /// </summary>
      protected override async void LoadChildren ()
      {
         var task = this.Connection.ChangeWorkingDirectory (this.GetDirectory ());
         var loader = new ModelTreeViewItem (this, false) { Text = "Loading...", Icon = MainMenuIcon.LoadingHourglass};
         this.Children.Add (loader);
         var items = new Collection <FtpItem> ();
         if (await task)
         {
            var files = await this.Connection.ListFiles ();
            foreach (var file in files)
            {
               if (file == "." || file == "..") continue;
               var isDir = await this.Connection.GetFileSize (file, true) <= 0;
               items.Add (new FtpItem (isDir, this.Connection, file, this));
            }
            this.Children.Remove (loader);
            foreach (var item in items.OrderBy (item => !item.IsDirectory))
               this.Children.Add (item);
         }
      }

      /// <summary>
      /// Gets the text of the item, removing any un-needed information.
      /// </summary>
      /// <returns>Formatted text of item.</returns>
      public string GetText ()
      {
         var text = this.Text;
         if (text.Contains ("->"))
         {
            var textSplit = text.Split (new [] { "->" }, StringSplitOptions.RemoveEmptyEntries);
            text = textSplit [0].Trim ();
         }
         return text;
      }

      /// <summary>
      /// Gets the full directory of this ftp item.
      /// </summary>
      /// <returns>Full directory path of this ftp item.</returns>
      public string GetDirectory ()
      {
         string dir = string.Empty;
         if (this.IsDirectory)
         {
            dir = this.GetText () + "/";
         }
         var parent = (FtpItem)this.Parent;
         while (parent != null && parent.IsDirectory)
         {
            dir = parent.GetText () + "/" + dir;
            parent = (FtpItem)parent.Parent;
         }

         return "/" + dir;
      }

      /// <summary>
      /// Sets the icon for the item..
      /// </summary>
      private void SetIcon ()
      {
         if (this.IsDirectory)
            this.Icon = MainMenuIcon.FolderClose;
         else if (this.IsRoot)
            this.Icon = MainMenuIcon.Ftp;
         else
            this.Icon = MainMenuIconConverter.GetIconForFile (this.Text);
      }

      /// <summary>
      /// Reloads the children of this item.
      /// </summary>
      public void Reload ()
      {
         if (this.IsDirectory || this.IsRoot)
         {
            this.Children.Clear ();
            this.LoadChildren ();
         }
      }
   }
}